import {
    Component, Input, OnChanges,
    SimpleChanges, ViewChild
} from '@angular/core';

import { Hero, ComponentBase } from '../share';

@Component({
    moduleId: module.id,
    selector: 'on-changes',
    template: `
  <div class="hero">
    <p>{{hero.name}} can {{power}}</p>
    <p><button (click)="resetPower()">Reset power</button></p>

    <h4>-- Change Log --</h4>
    <div *ngFor="let chg of changeLog">{{chg}}</div>
  </div>
  `,
    styles: [
        '.hero {background: LightYellow; padding: 8px; margin-top: 8px}',
        'p {background: Yellow; padding: 8px; margin-top: 8px}'
    ]
})
export class OnChangesComponent extends ComponentBase implements OnChanges {
    _hero: Hero;
    _power: string;

    changeLog: string[] = [];

    constructor() {
        super();
    }

    @Input() get hero(): Hero {
        this.internalConsoleLog('Input of hero get');
        return this._hero;
    }

    set hero(value: Hero) {
        this.internalConsoleLog('Input of hero set');
        this._hero = value;
    }

   @Input() get power(): string {
        this.internalConsoleLog('Input of power get');
        return this._power;
    }

    set power(value: string) {
        this.internalConsoleLog('Input of power set');
        this._power = value;
    }

    ngOnChanges(changes: SimpleChanges) {
        super.ngOnChanges(changes);
        for (let propName in changes) {
            let chng = changes[propName];
            let cur = JSON.stringify(chng.currentValue);
            let prev = JSON.stringify(chng.previousValue);
            this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
        }
    }

    resetPower() {
        this.power = 'sing';
    }

    reset() { this.changeLog.length = 0; }
}

/***************************************/

@Component({
    moduleId: module.id,
    selector: 'on-changes-parent',
    templateUrl: './onChangesParent.component.html',
    styles: ['.parent {background: Lavender;}']
})
export class OnChangesParentComponent extends ComponentBase implements OnChanges {
    hero: Hero;
    power: string;
    title = 'OnChanges';
    @ViewChild(OnChangesComponent) childView: OnChangesComponent;
    @Input() test = 'app works!';
    @Input() unUsedInputToUnchangesWhenNotFirstLoaded: boolean;

    constructor() {
        super();
        this.reset();
         this.hero = new Hero('Windstorm');
    }

    reset() {
        // new Hero object every time; triggers onChanges
        // this.hero = new Hero('Windstorm');
        // setting power only triggers onChanges if this value is different
        this.power = 'sing';
        if (this.childView) { this.childView.reset(); }
    }

    ngOnChanges(changes: SimpleChanges) {
        super.ngOnChanges(changes);
    }
}


/**
 * Remark:
 *    1. onChanges 只有在@Input() 参数被使用的时候才会触发.
 *       1.1: 第一次触发onChanges时，
 *              @Input()被使用的参数都被标记为changed(无论Input值是否与初始化值相同,通过打印日志发现其没有调用get再set).
 *              未被使用的参数不会被标记changed.
 *       1.2: 非第一次时，@Input()参数未发生变化时，不会被标记为changed.也没有调用get，猜测是ng内置机制记录了@Input参数的PreValue.
 *    2. 如果是对象(引用)时，虽然对象的属性发生了变化，但是其引用没有变化，Angular不会将其标记为changed.
 *    3. 尽量不要在属性的get\set,主要是get方法里面写太复杂的逻辑，因为属性的get方法会被频繁的调用.
 *    4. ng是先给@Input参数设置值，再调用ngOnChanges.--->在ngOnchanges里面是第一次访问这些值得hook，但是ngOnchanges会被调用多次。
 */
